﻿using System.Net;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Ftp;
using UtilZ.Dotnet.Ex.Communication.Net.Web;
using UtilZ.Dotnet.Ex.Log;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZFileServer
{
    internal class Program
    {
        static void Main(string[] args)
        {
            InitLog();

            try
            {
                var config = Config.Instance;
                Console.Title = config.ServiceName;

                int disposeOrder = 0;
                using (var disposabler = new Disposabler())
                {
                    if (config.HttpPort > 0)
                    {
                        string[] dirs = config.LocalPaths.Select(t => { return t.Path; }).ToArray();

                        var handler = new HttpRequestHandler();

                        var apiMiddleware = new ApiMiddleware();
                        apiMiddleware.AddApi(new FileServerApi(config.LocalPaths));
                        handler.AddMiddleware(apiMiddleware, 10);

                        var appDir = PathEx.GetEntryAssemblyDirectory();
                        var dirInfo = new DirectoryInfo(appDir);
                        string rootDir = null;
#if DEBUG
                        if (dirInfo.Parent != null && dirInfo.Parent.Parent != null && dirInfo.Parent.Parent.Parent != null)
                        {
                            rootDir = PathEx.Combine(PathType.Local, dirInfo.Parent.Parent.Parent.FullName, "htmls");
                        }
#endif

                        if (string.IsNullOrWhiteSpace(rootDir) || !Directory.Exists(rootDir))
                        {
                            rootDir = PathEx.Combine(PathType.Local, "htmls");
                        }

                        var webSiteConfig = new WebSiteConfig(rootDir, "index.html", dirs);
                        webSiteConfig.ResourceProvider = new WebSiteIEResourceProvider();
                        handler.AddMiddleware(new WebSiteMiddleware(webSiteConfig), 100);


                        var httpconfig = new HttpServerConfig();
                        httpconfig.MaxConnections = config.MaxConnections;
                        httpconfig.ListenEndPoint = new IPEndPoint(IPAddress.Any, config.HttpPort);
                        HttpServer httpServer = new HttpServer(httpconfig, handler);
                        disposabler.Add(httpServer, disposeOrder++);
                        httpServer.Start();
                        Loger.Info("http server 启动完成");
                    }

                    if (config.FtpCommandPort > 0)
                    {
                        var ftpconfig = new FtpConfig()
                        {
                            RootPathItems = config.LocalPaths.Select(t => { return new LocalPathItem(t.Alias, t.Path); }).ToList(),
                            EndPoint = new IPEndPoint(IPAddress.Any, config.FtpCommandPort),
                            PortModePort = config.PortModePort,
                            PassiveMinPort = config.PassiveMinPort,
                            PassiveMaxPort = config.PassiveMaxPort,
                            PassiveIgnorePortList = config.PassiveIgnorePortList,
                        };
                        var ftpServer = new FtpServer(ftpconfig);
                        disposabler.Add(ftpServer, disposeOrder++);
                        ftpServer.Start();
                        Loger.Info("ftp server 启动完成");
                    }

                    if (disposeOrder > 0)
                    {
                        Loger.Info("q exit");

                        if (!config.ShowProcessWindow)
                        {
                            if (EnvironmentEx.IsWindowPlatform())
                            {
#pragma warning disable CA1416
                                ConsoleEx.HideConsole(Console.Title);
#pragma warning restore CA1416
                            }
                        }

                        ConsoleKeyInfo consoleKey;
                        while (true)
                        {
                            consoleKey = Console.ReadKey();
                            if (consoleKey.Key == ConsoleKey.Q)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        Loger.Warn("没有启用项");
                    }
                }
            }
            catch (Exception ex)
            {
                Loger.Fatal(ex);

                ConsoleKeyInfo consoleKey;
                while (true)
                {
                    consoleKey = Console.ReadKey();
                    if (consoleKey.Key == ConsoleKey.Q)
                    {
                        break;
                    }
                }
            }
        }



        private static void InitLog()
        {
            ZLoger.OutputOption = ZLogerOutputOptions.Loger;
            var redirectAppenderToUI = (RedirectAppender)Loger.GetAppenderByName(null, "RedirectToUI");
            if (redirectAppenderToUI != null)
            {
                redirectAppenderToUI.RedirectOuput += RedirectLogOutput;
            }
        }

        private static void RedirectLogOutput(object sender, RedirectOuputArgs e)
        {
            ConsoleColor fontColor;
            string str;
            try
            {
                var item = e.Item;
                str = string.Format("{0} {1}", e.Item.Time.ToString(LogConstant.DateTimeFormat), e.Item.Content);

                switch (item.Level)
                {
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Trace:
                        fontColor = ConsoleColor.Gray;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Debug:
                        fontColor = ConsoleColor.Gray;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Info:
                        fontColor = ConsoleColor.White;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Warn:
                        fontColor = ConsoleColor.Yellow;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Error:
                        fontColor = ConsoleColor.Red;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Fatal:
                        fontColor = ConsoleColor.Red;
                        break;
                    default:
                        return;
                }
            }
            catch (Exception ex)
            {
                fontColor = ConsoleColor.Red;
                str = ex.Message;
            }

            var oldForegroundColor = Console.ForegroundColor;
            Console.ForegroundColor = fontColor;
            Console.WriteLine(str);
            Console.ForegroundColor = oldForegroundColor;
        }
    }
}